package com.hsj.common.gateway.filter;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.nacos.shaded.com.google.common.base.Joiner;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.hsj.common.gateway.constants.Constants;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
@Component
@Configuration
public class ResponseGlobalFilter implements WebFilter, Ordered {

    private static Joiner joiner = Joiner.on("");//将 List 数据以""分隔进行拼接

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        ServerHttpResponse originalResponse = exchange.getResponse();
        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {

                if (body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                    return super.writeWith(fluxBody.buffer().map(dataBuffers  -> {
                        List<String> list = Lists.newArrayList();
                        dataBuffers.forEach(dataBuffer -> {
                            byte[] content = new byte[dataBuffer.readableByteCount()];
                            dataBuffer.read(content);
                            DataBufferUtils.release(dataBuffer);
                            try {
                                list.add(new String(content, StandardCharsets.UTF_8));
                            } catch (Exception e) {
                                log.error("--list.add--error",e);
                            }
                        });
                        String responseMsg =  joiner.join(list);        ;
                        JSON response;
                        try {
                            response = JSONUtil.parse(responseMsg);
                        }catch(JSONException e){
                            response = null;
                        }

                        byte[] bytes;
                        if(response == null){
                            Map<String, Object> message = new HashMap();
                            message.put(Constants.CODE, "000000");
                            message.put(Constants.MSG, "交互成功");
                            message.put(Constants.DATA, responseMsg);
                            bytes = JSONUtil.toJsonStr(message).getBytes();
                        }else{
                            if(response instanceof JSONObject && ((JSONObject)response).containsKey(Constants.CODE) && ((JSONObject)response).containsKey(Constants.MSG)){
                                bytes = responseMsg.getBytes();
                            }else{
                                Map<String, Object> message = new HashMap();
                                message.put(Constants.CODE, "000000");
                                message.put(Constants.MSG, "交互成功");
                                message.put(Constants.DATA, response);
                                bytes = JSONUtil.toJsonStr(message).getBytes();
                            }
                        }
                        originalResponse.getHeaders().setContentLength(bytes.length);
                        //不处理异常则用json转换前的数据返回
                        return bufferFactory.wrap(bytes);
                    }));
                }
                return super.writeWith(body);
            }
        };
        return chain.filter(exchange.mutate().response(decoratedResponse).build());
    }

//    /**
//     * 返回值处理
//     *
//     * @param exchange
//     * @param chain
//     * @return
//     */
//    @Override
//    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
//        ServerHttpResponse originalResponse = exchange.getResponse();
//        DataBufferFactory bufferFactory = originalResponse.bufferFactory();
//        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
//            @Override
//            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
//                if (body instanceof Flux) {
//                    if (ContentType.JSON.toString()
//                            .equals(originalResponse.getHeaders().getFirst(Header.CONTENT_TYPE.toString()))) {
//                        Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>)body;
//                        return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
//                            DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
//                            DataBuffer join = dataBufferFactory.join(dataBuffers);
//                            byte[] content = new byte[join.readableByteCount()];
//                            join.read(content);
//                            // 释放掉内存
//                            DataBufferUtils.release(join);
//                            String responseData = new String(content, Charsets.UTF_8);
//                            System.out.println("-----------------");
//                            System.out.println(responseData);
//                            byte[] uppedContent = responseData.getBytes(Charsets.UTF_8);
//                            return bufferFactory.wrap(uppedContent);
//                        }));
//                    }
//                }
//                return super.writeWith(body);
//            }
//
//        };
//        // replace response with decorator
//        return chain.filter(exchange.mutate().response(decoratedResponse).build());
//    }

    @Override
    public int getOrder() {
        return -2;
    }
}